#pragma once

#include <opencv2/opencv.hpp>

#include "ObCommon.h"
#include "OpenNI.h"
#include "camera.hpp"
#include "usb.hpp"

#define DEPTH_TIMEOUT 500

// using namespace openni;
typedef enum {
  HARDWARE_D2C = 0,
  SOFTWARE_D2C = 1,
  NORMAL_NO = 2,
} ObD2CType;

namespace Orbbec {

constexpr int kL_400 = 400;
constexpr int kL_480 = 480;
constexpr int kL_640 = 640;

constexpr int COLOR_IS_MIRROR = 1;
constexpr int kPID_0402 = 0x0402;

void GetDepthHistogram(cv::Mat &src, cv::Mat &dst);

}  // namespace Orbbec

class Astra {
 private:
  openni::Device device_;
  openni::VideoStream depth_stream_;
  openni::VideoStream color_stream_;
  bool depth_init_;
  bool depth_start_;
  bool depth_stream_create_;
  bool color_start_;
  bool color_stream_create_;
  float *histogram_;

  ObCameraStatus DepthInit(void);
  ObCameraStatus DepthUnInit();
  ObCameraStatus DepthStart(int width, int height);
  ObCameraStatus DepthStop();
  ObCameraStatus WaitDepthStream(openni::VideoFrameRef &frame);
  void CalcDepthHist(openni::VideoFrameRef &frame);

  int image_width_;
  int image_height_;

  ObCameraStatus ColorStart(int width, int height);
  ObCameraStatus ColorStop();
  ObCameraStatus WaitColorStream(openni::VideoFrameRef &frame);

 public:
  Astra();
  ~Astra();

  ObCameraStatus CameraInit(int d2cType);
  ObCameraStatus CameraUnInit();
  ObCameraStatus GetStreamData(cv::Mat &cv_rgb, cv::Mat &cv_depth);
  ObCameraStatus StreamStop();

  ObCameraStatus SetD2CType(int decType);
  uint16_t GetDevicePid();

  /**
   * @brief Get the Camera Param object 获取相机的内外参
   *
   * @param cameraParam 相机的内外参
   * @return int
   *   success : 0
   *   failure : !0
   */
  ObCameraStatus GetCameraParam(OBCameraParams &cameraParam);

  /**
   * @brief Get the Camera Resolution object 获取Depth分辨率
   *
   * @param nImageWidth 图像宽
   * @param nImageHeight 图像高
   * @return int
   *   success:  CAMERA_STATUS_SUCCESS
   *   failure:  CAMERA_STATUS_DEPTH_GET_RESOLUTION_FAIL
   */
  ObCameraStatus GetCameraResolution(int &nImageWidth, int &nImageHeight);

 protected:
  int type_;
};

std::string StatusToString(ObCameraStatus event);
void WarnReport(ObCameraStatus event);
void WarnReport(bool event, const std::string &args);